package com.ysjsgzq.index;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import com.alibaba.fastjson.JSONObject;
import com.jfinal.core.Controller;
import com.jfinal.kit.Kv;
import com.jfinal.kit.LogKit;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.jfinal.upload.UploadFile;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.setting.Setting;
/**
 * IndexController 指向系统访问首页
 * @author LiNing
 * @email 969515698@qq.com
 */
public class IndexController extends Controller {
	
	public static Setting FILE_SETTING = new Setting(FileUtil.touch("file_upload.setting"),CharsetUtil.CHARSET_UTF_8, true);
	private static Lock lock = new ReentrantLock();//生成一个锁，避免多线程
	
	/**
	 * 首页Action
	 */
	public void index() {
		render("index.html");
	}
	
	/**
	 * 获取已经上传成功的文件碎片
	 */
	public void getSucIndexs() {
		lock.lock();
		try {
			
			Kv kv = getKv();//接收浏览器传过来的参数
			int total = getInt("total");//文件碎片总个数
			
			String sign = DigestUtil.md5Hex(kv.getStr("name")+kv.getStr("total"));		
			JSONObject file_json=getFileJson(sign, kv.getStr("name"), total);
			List<Integer> succ_indexs=(List<Integer>) file_json.get("succ_indexs");
			
			renderJson(Ret.ok("succ_indexs",CollUtil.join(succ_indexs, ",")));
		} catch (Exception e) {
			
		}finally {
			lock.unlock();
		}
		
	}
	
	/**
	 * 大文件断点续传
	 */
	public void uploadMulit() {
		lock.lock();
		try {
			//接收上传的文件
			UploadFile uploadFile = getFile();
			
			Kv kv = getKv();//接收浏览器传过来的参数
			
			//文件名+文件碎片个数 进行md5计算生成一个签名
			String sign = DigestUtil.md5Hex(kv.getStr("name")+kv.getStr("total"));		
			
			int total = getInt("total");
			//根据签名读取配置文件
			JSONObject file_json=getFileJson(sign, kv.getStr("name"), total);
			//获取已经上传成功的碎片下标
			List<Integer> succ_indexs=(List<Integer>) file_json.get("succ_indexs");
			//当前碎片的下标添加到集合
			succ_indexs.add(getParaToInt("index"));
			
			file_json.put("count", file_json.getIntValue("count")+1);
			file_json.put("succ_indexs", succ_indexs);
			saveFileJson(file_json,sign);//重新保存配置信息
			if(file_json.getIntValue("count") == total) {
				File sourceFile = null;
				//文件的名字(带后缀)
				String uploadname = kv.getStr("name");
				//获取文件后缀名
				String suffix = uploadname.substring(uploadname.lastIndexOf(".")+1);
				//生成一个新的uuid
				String uuid = UUID.randomUUID().toString().replaceAll("-", "");
				//文件重命名(uuid命名)
				String uuidname = uuid +"."+suffix;
				
				//文件上传后的路径
				String path =uploadFile.getUploadPath()+File.separatorChar+uuidname;
				
				File targetFile = new File(path);
				RandomAccessFile readFile = null;
				RandomAccessFile writeFile = null;
				try {
					writeFile = new RandomAccessFile(targetFile, "rw");
					long last_position=1;
					for(int i=1;i<= total;i++) {
						sourceFile = new File(uploadFile.getUploadPath()+File.separatorChar+uploadname+i+".temp");
						last_position =targetFile.length();
						
						if(sourceFile.exists()) {
							readFile = new RandomAccessFile(sourceFile, "rw");
							readFile.seek(0);
							writeFile.seek(last_position);
							
							// 数据缓冲区
							byte[] buf = new byte[1024];
							// 数据读写
							while (readFile.read(buf) != -1) {
								writeFile.write(buf);
							}
							readFile.close();//关闭读取流
						}
						
						FileUtil.del(sourceFile);//删除临时文件
					}
					
				} catch (FileNotFoundException e) {
					LogKit.error("文件合并失败",e);
				} catch (IOException e) {
					LogKit.error("文件合并失败",e);
				}finally {
					if(null != readFile) {
						try {
							readFile.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
					
					if(null !=writeFile) {
						try {
							writeFile.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}
				//移除记录
				removeFileJson(sign);
				//响应浏览器上传成功
				renderJson(Ret.ok("isover",true).set("count", file_json.getIntValue("count")).set("path", path).set("file_name", uuidname));
			}else {
				//响应浏览器上传成功	
				renderJson(Ret.ok("count", file_json.getIntValue("count")));
			}
		} catch (IORuntimeException e) {
			
		}finally {
			lock.unlock();
		}
		
	}
	
	/**
	 * 读取文件上传个数
	 * @param sign
	 * @param name
	 * @param total
	 * @return
	 */
	private JSONObject getFileJson(String sign,String name,int total) {
		
		String file_info=FILE_SETTING.get(sign);
		JSONObject file_json = null;
		if(StrKit.notBlank(file_info)) {
			file_json = JSONObject.parseObject(file_info);
		}else {
			file_json = new JSONObject();
			file_json.put("name", name);
			file_json.put("total", total);
			file_json.put("count", 0);
			file_json.put("succ_indexs", new ArrayList<Integer>());//已经上传成功的文件碎片下标
		}
		return file_json;
	}
	
	/**
	 * 保存文件上传个数
	 * @param file_json
	 * @param sign
	 */
	private void saveFileJson(JSONObject file_json,String sign) {
		FILE_SETTING.set(sign,file_json.toJSONString());
		FILE_SETTING.store("file_upload.setting");//保存一次
	}
	
	/**
	 * 移除已经上传成功的文件
	 * @param sign
	 */
	private void removeFileJson(String sign) {
		FILE_SETTING.remove(sign);
		FILE_SETTING.store("file_upload.setting");//保存一次
	}
}